"""
划词翻译工具 - 信号处理方案 (improved_main.py)

实现特点：
- ❌ 无系统托盘：不包含托盘功能，更轻量
- ✅ 信号处理：优雅处理 Ctrl+C 和 SIGTERM 信号
- ✅ 线程安全：使用 mainloop() 避免线程问题
- ✅ 简洁：代码更简洁，依赖更少
- ✅ 跨平台兼容：支持 Windows/macOS/Linux

适用场景：不需要系统托盘功能，希望程序更轻量
依赖：pynput, pyperclip, requests
"""

import time
import pyperclip
import tkinter as tk
from tkinter import ttk
from pynput import mouse, keyboard
from pynput.mouse import Button, Controller
from pynput.keyboard import Key, Controller as KeyboardController
import requests
import threading
import signal
import sys
import os

# 全局变量：记录鼠标状态
is_selecting = False
start_x, start_y = 0, 0
mouse_controller = Controller()
keyboard_controller = KeyboardController()

# 全局窗体管理
current_window = None
mouse_listener_active = False
global_mouse_listener_thread = None

# 当前选中的文字
current_selected_text = None

# 全局tkinter根窗口（避免重复创建）
main_root = None

# 程序运行状态
program_running = True

# 信号处理函数
def signal_handler(signum, frame):
    """处理退出信号"""
    global program_running
    print("\n收到退出信号，正在安全退出...")
    program_running = False
    cleanup_resources()
    sys.exit(0)

# 注册信号处理器
signal.signal(signal.SIGINT, signal_handler)  # Ctrl+C
signal.signal(signal.SIGTERM, signal_handler)  # 终止信号

# 翻译功能（示例：使用百度翻译API，需自行申请密钥）
class Translator:
    def __init__(self, appid, secret_key):
        self.appid = appid
        self.secret_key = secret_key
        self.url = 'https://fanyi-api.baidu.com/api/trans/vip/translate'

    def translate(self, text, from_lang='auto', to_lang='zh'):
        if not text.strip():
            return "无选中内容"
        
        # 使用模板字符串输出翻译结果
        return f"翻译：{text}"

# 悬浮菜单窗口
class FloatMenu(tk.Toplevel):
    def __init__(self, parent, x, y, text, translator):
        super().__init__(parent)
        self.translator = translator
        self.text = text
        
        # 窗口配置：无边框、置顶、透明背景
        self.overrideredirect(True)  # 无边框
        self.attributes('-topmost', True)  # 始终置顶
        self.attributes('-alpha', 0.9)  # 透明度
        
        # 定位到鼠标位置附近
        self.geometry(f"+{x+10}+{y+10}")
        
        # 菜单内容
        self.create_widgets()
        
        # 绑定点击事件
        self.bind("<Button-1>", self.on_click)
        
        # 设置全局当前窗口
        global current_window
        if current_window:
            current_window.destroy()
        current_window = self
        
        # 启动鼠标监听线程来检测点击窗体外部
        start_global_mouse_listener()
    
    def on_click(self, event):
        # 点击窗体内部不关闭
        pass
    
    def destroy(self):
        global current_window, mouse_listener_active, global_mouse_listener_thread
        if current_window == self:
            current_window = None
            mouse_listener_active = False
            # 等待线程结束
            if global_mouse_listener_thread and global_mouse_listener_thread.is_alive():
                global_mouse_listener_thread = None
        super().destroy()

    def create_widgets(self):
        frame = ttk.Frame(self, padding=5)
        frame.pack()
        
        # 显示选中的文本（简短预览）
        preview = self.text[:30] + ('...' if len(self.text) > 30 else '')
        ttk.Label(frame, text=preview, wraplength=300).pack(pady=2)
        
        # 功能按钮
        btn_frame = ttk.Frame(frame)
        btn_frame.pack(pady=5)
        
        ttk.Button(btn_frame, text="翻译", command=self.do_translate).grid(row=0, column=0, padx=5)
        ttk.Button(btn_frame, text="复制", command=self.do_copy).grid(row=0, column=1, padx=5)
        ttk.Button(btn_frame, text="关闭", command=self.destroy).grid(row=0, column=2, padx=5)

    def do_translate(self):
        result = self.translator.translate(self.text)
        # 显示翻译结果
        self.destroy()
        FloatResult(self.master, self.winfo_x(), self.winfo_y(), result)

    def do_copy(self):
        pyperclip.copy(self.text)
        self.destroy()

# 翻译结果窗口
class FloatResult(tk.Toplevel):
    def __init__(self, parent, x, y, result):
        super().__init__(parent)
        self.overrideredirect(True)
        self.attributes('-topmost', True)
        self.attributes('-alpha', 0.9)
        self.geometry(f"+{x}+{y+50}")
        
        # 绑定点击事件
        self.bind("<Button-1>", self.on_click)
        
        # 设置全局当前窗口
        global current_window
        if current_window:
            current_window.destroy()
        current_window = self
        
        # 启动鼠标监听
        start_global_mouse_listener()
        
        ttk.Label(self, text="翻译结果:", font=('Arial', 10, 'bold')).pack(pady=2)
        ttk.Label(self, text=result, wraplength=300).pack(padx=5, pady=5)
        ttk.Button(self, text="关闭", command=self.destroy).pack(pady=3)
    
    def on_click(self, event):
        # 点击窗体内部不关闭
        pass
    
    def destroy(self):
        global current_window, mouse_listener_active, global_mouse_listener_thread
        if current_window == self:
            current_window = None
            mouse_listener_active = False
            # 等待线程结束
            if global_mouse_listener_thread and global_mouse_listener_thread.is_alive():
                global_mouse_listener_thread = None
        super().destroy()

# 改进的文本选择检测（避免模拟复制）
def get_selected_text_alternative():
    """
    替代方案：直接获取剪贴板内容
    注意：这需要用户先手动复制文本
    """
    try:
        # 保存当前剪贴板内容
        original_clipboard = pyperclip.paste()
        
        # 模拟复制操作
        simulate_copy()
        time.sleep(0.1)  # 等待剪贴板更新
        
        # 获取复制后的内容
        selected_text = pyperclip.paste()
        
        # 恢复原始剪贴板内容
        if original_clipboard != selected_text:
            pyperclip.copy(original_clipboard)
        
        return selected_text if selected_text != original_clipboard else None
    except Exception as e:
        print(f"获取选中文本失败: {e}")
        return None

# 模拟复制操作
def simulate_copy():
    """根据系统使用不同的复制快捷键"""
    from sys import platform
    if platform == "darwin":  # macOS
        keyboard_controller.press(Key.cmd)
        keyboard_controller.press('c')
        keyboard_controller.release('c')
        keyboard_controller.release(Key.cmd)
    else:  # Windows/Linux
        keyboard_controller.press(Key.ctrl)
        keyboard_controller.press('c')
        keyboard_controller.release('c')
        keyboard_controller.release(Key.ctrl)

# 启动全局鼠标监听
def start_global_mouse_listener():
    """启动全局鼠标监听"""
    global mouse_listener_active, global_mouse_listener_thread
    if not mouse_listener_active:
        mouse_listener_active = True
        # 启动全局鼠标监听
        global_mouse_listener_thread = threading.Thread(target=global_mouse_listener, daemon=True)
        global_mouse_listener_thread.start()

# 全局鼠标监听函数
def global_mouse_listener():
    """全局鼠标监听，检测点击窗体外部"""
    global current_window, mouse_listener_active
    
    def on_global_click(x, y, button, pressed):
        if button == Button.left and pressed and current_window:
            try:
                # 获取当前窗体的位置和大小
                window_x = current_window.winfo_x()
                window_y = current_window.winfo_y()
                window_width = current_window.winfo_width()
                window_height = current_window.winfo_height()
                
                # 检查点击是否在窗体外部
                if not (window_x <= x <= window_x + window_width and 
                       window_y <= y <= window_y + window_height):
                    # 点击在窗体外部，关闭窗体
                    current_window.destroy()
            except:
                pass
    
    # 启动鼠标监听
    try:
        with mouse.Listener(on_click=on_global_click) as listener:
            while mouse_listener_active and current_window and program_running:
                time.sleep(0.1)
            listener.stop()
    except Exception as e:
        print(f"鼠标监听器错误: {e}")

# 鼠标事件处理
def on_mouse_press(x, y, button, pressed):
    global is_selecting, start_x, start_y
    if button == Button.left:
        if pressed:
            # 记录鼠标按下位置
            is_selecting = True
            start_x, start_y = x, y
        else:
            # 鼠标释放时判断是否为选择操作
            if is_selecting and (abs(x - start_x) > 5 or abs(y - start_y) > 5):
                # 使用改进的文本获取方法
                threading.Thread(target=copy_and_process_improved, daemon=True).start()
            is_selecting = False
            
            # 处理双击：如果距离上次点击时间很短且位置相近，认为是双击
            current_time = time.time()
            if hasattr(on_mouse_press, 'last_click_time') and hasattr(on_mouse_press, 'last_click_pos'):
                time_diff = current_time - on_mouse_press.last_click_time
                pos_diff = abs(x - on_mouse_press.last_click_pos[0]) + abs(y - on_mouse_press.last_click_pos[1])
                
                # 双击条件：时间间隔小于0.5秒，位置差异小于10像素
                if time_diff < 0.5 and pos_diff < 10:
                    threading.Thread(target=copy_and_process_improved, daemon=True).start()
                    return
            
            # 记录本次点击信息
            on_mouse_press.last_click_time = current_time
            on_mouse_press.last_click_pos = (x, y)


def copy_and_process_improved():
    global current_selected_text
    
    # 使用改进的文本获取方法
    selected_text = get_selected_text_alternative()
    
    if selected_text and selected_text.strip():
        current_selected_text = selected_text
        
        # 打印选中的文字到控制台
        print(f"选中的文字: {selected_text}")
        print(f"文字长度: {len(selected_text)} 字符")
        
        # 获取当前鼠标位置
        x, y = mouse_controller.position
        
        # 检查是否已有窗口存在，如果有则先关闭
        global current_window
        if current_window:
            current_window.destroy()
        
        # 在主线程中创建悬浮菜单
        show_float_menu(x, y, selected_text)

def show_float_menu(x, y, selected_text):
    """在主线程中显示悬浮菜单"""
    global main_root
    
    # 初始化翻译器（替换为你的API密钥）
    translator = Translator(appid="YOUR_APPID", secret_key="YOUR_SECRET")
    # 显示悬浮菜单
    FloatMenu(main_root, x, y, selected_text, translator)

# 清理资源函数
def cleanup_resources():
    """清理所有资源"""
    global current_window, mouse_listener_active, global_mouse_listener_thread, main_root
    
    # 关闭当前窗口
    if current_window:
        current_window.destroy()
        current_window = None
    
    # 停止鼠标监听
    mouse_listener_active = False
    global_mouse_listener_thread = None
    
    # 清理tkinter根窗口
    if main_root:
        try:
            main_root.quit()
            main_root.destroy()
        except:
            pass
        main_root = None

# 启动监听
def start_listening():
    global main_root, program_running
    
    # 创建全局tkinter根窗口
    main_root = tk.Tk()
    main_root.withdraw()  # 隐藏主窗口
    
    try:
        # 启动鼠标监听线程
        mouse_thread = threading.Thread(target=run_mouse_listener, daemon=True)
        mouse_thread.start()
        
        print("开始监听划词操作（按Ctrl+C或发送SIGTERM信号退出）")
        print("提示：选中文字后会自动复制并显示悬浮菜单")
        
        # 使用 mainloop() 而不是手动循环
        main_root.mainloop()
                
    except Exception as e:
        print(f"程序运行错误: {e}")
    finally:
        # 程序退出时清理资源
        cleanup_resources()

def run_mouse_listener():
    """在后台线程中运行鼠标监听"""
    with mouse.Listener(on_click=on_mouse_press) as listener:
        try:
            while program_running:
                time.sleep(0.1)
        except Exception as e:
            print(f"鼠标监听器错误: {e}")

if __name__ == "__main__":
    start_listening()
